/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package vnetlab.ui;

import com.mxgraph.model.mxCell;
import com.mxgraph.model.mxICell;
import com.mxgraph.util.mxEvent;
import com.mxgraph.util.mxEventObject;
import com.mxgraph.util.mxEventSource.mxIEventListener;
import javax.swing.JOptionPane;
import vnetlab.elements.*;
import vnetlab.manager.Configuration;
import vnetlab.manager.Manager;
import vnetlab.ui.editor.EditorInterfaceChooser;
import vnetlab.virtualbox.VirtualBoxManager;

/**
 *
 * @author ROGERIO e PAOLO
 *
 * Classe para tratar os eventos de manipulação
 */
public class CustomEventListner implements mxIEventListener {

    public void invoke(Object sender, mxEventObject evt) {

        String name = evt.getName();

        //Quando uma celula for adicionada
        if (name.equals(mxEvent.CELLS_ADDED)) {
            cellsAddedAction(evt);
        } //Quando uma celula for removida
        else if (name.equals(mxEvent.CELLS_REMOVED)) {
            cellsRemovedAction(evt);
        } //Quando uma celula for ligada a outra
        else if (name.equals(mxEvent.CELL_CONNECTED)) {
            cellsConnectedAction(evt);
        }

    }

    private void cellsAddedAction(mxEventObject evt) {

        Object[] o = (Object[]) evt.getProperty("cells");
        mxCell c = (mxCell) o[0];

        addCell(c);

    }

    public static void addCell(mxCell c) {

        Element element = null;

        boolean isConection = false; // Variavel utilizada para descobir se o elemento incluido é uma conexão entre dois elementos

        if (c.getValue() instanceof String) {
            //Pega o tipo do elemento e o id dele
            String tipo = ((String) c.getValue()).split("_")[0];
            String id = c.getId();

            //De acordo com o tipo, instancia o elemento adequado
            // e adiciona em uma lista de elementos

            if (tipo.equals("Computer")) {
                c.setValue(tipo + "_" + c.getId());
                String s = (String) c.getValue();
                element = new Computer(s, id, "Computer", Configuration.getInstance().getComputerTemplate());
                element.addInterface(new Interface(0,  false), 0);

            } else if (tipo.equals("Router")) {
                c.setValue(tipo + "_" + c.getId());
                String s = (String) c.getValue();
                element = new Router(s, id, "Router", Configuration.getInstance().getRouterTemplate());
                for (int i = 0; i < element.numberOfNIC(); i++) {
                    element.addInterface(new Interface(i,  false), i);
                }

            } else if (tipo.equals("Server")) {
                c.setValue(tipo + "_" + c.getId());
                String s = (String) c.getValue();
                element = new Server(s, id, "Server", Configuration.getInstance().getServerTemplate());
                for (int i = 0; i < element.numberOfNIC(); i++) {
                    element.addInterface(new Interface(i, false), i);
                }

            } else if (tipo.equals("Switch")) {
                c.setValue(tipo + "_" + c.getId());
                String s = (String) c.getValue();
                element = new Switch(s, id, "Switch", 10);
                for (int i = 0; i < element.numberOfNIC(); i++) {
                    element.addInterface(new Interface(i, false), i);
                }
            } //Está incluindo um elemento que representa a ligação entre dois elementos da topologia
            else if (c.getSource() != null && c.getTarget() != null) {

                isConection = true;//Indica que é uma conexão

                mxICell source = c.getSource();
                mxICell target = c.getTarget();

                Element eSource = Manager.getInstance().getElement(source.getId());
                Element eTarget = Manager.getInstance().getElement(target.getId());

                if (!eSource.getType().equals("Switch") || !eTarget.getType().equals("Switch")) {

                    boolean inserted = true;

                    int sourceInterface = eSource.idTarget(eTarget.getName());
                    int targetInterface = eTarget.idTarget(eSource.getName());


                    //Caso existam os atributos, significa que esta recarregando o arquivo
                    if (sourceInterface >= 0 && targetInterface >= 0) {
                        inserted = false;
                    }

                    //Verifica se existe alguma interface de rede disponível caso seja uma operação de insert
                    if (!inserted || (eSource.checkInterfaceAvailable() && eTarget.checkInterfaceAvailable())) {

                        EditorInterfaceChooser chooser = new EditorInterfaceChooser(eSource, eTarget);
                        int status = 0;

                        //Se está inserindo, então mostra a janela para escolher as interfaces
                        if (inserted) {
                            chooser.setVisible(true);
                            status = chooser.getReturnStatus();
                        } else {
                            status = EditorInterfaceChooser.RET_OK;
                        }

                        //Se foi fechado com o ok, então continua
                        if (status == EditorInterfaceChooser.RET_OK) {

                            if (inserted) {
                                //Utiliza os valores selecionados para as interfaces
                                sourceInterface = chooser.getSourceInterface();
                                targetInterface = chooser.getTargetInterface();
                            }

                            if (eTarget.getType().equals("Switch") || eSource.getType().equals("Switch")) {
                                eTarget.connect(targetInterface, eSource.getName(), eSource.getType());
                                eSource.connect(sourceInterface, eTarget.getName(), eTarget.getType());
                            } else {
                                eTarget.connect(targetInterface, eTarget.getName() + eSource.getName(), eSource.getType());
                                eSource.connect(sourceInterface, eTarget.getName() + eSource.getName(), eTarget.getType());
                            }
                        } //Se não houver interfaces de rede livre no momento, então exclui a ligação criada
                        else {
                            c.removeFromParent();
                            return;
                        }
                    } //Se não houver interfaces de rede livre no momento, então exclui a ligação criada
                    else {
                        c.removeFromParent();
                        return;
                    }
                } else {
                    JOptionPane.showMessageDialog(null, "Connection between two switches is not available.");
                    c.removeFromParent();
                    return;
                }
            }
        } else if (!isConection) {
            element = (Element) c.getValue();
        }
        else if(!isConection){
            element = (Element)c.getValue();
            
        }

        //Insere o elemento, se não for uma ligação entre dois elementos
        if (!isConection) {
            c.setValue(element);
            
            Manager.getInstance().addElement(element);//id, tipo, comp, rt, sv, sw);
        }
    }

    private void cellsRemovedAction(mxEventObject evt) {
        Object[] objects = (Object[]) evt.getProperty("cells");
        mxCell c = null;//(mxCell) o[0];

        for (Object o : objects) {

            c = (mxCell) o;
            if (c.getSource() != null && c.getTarget() != null) {
                Element eSource = Manager.getInstance().getElement(c.getSource().getId());
                Element eTarget = Manager.getInstance().getElement(c.getTarget().getId());

                if (eSource != null && eSource.idTarget(eTarget.getName()) != -1) {
                    eSource.disconnect(eSource.idTarget(eTarget.getName()), "null", "null");
                }

                if (eTarget != null && eTarget.idTarget(eSource.getName()) != -1) {
                    eTarget.disconnect(eTarget.idTarget(eSource.getName()), "null", "null");
                }

            }
        }

        for (Object o : objects) {

            c = (mxCell) o;
            if (c.getSource() == null || c.getTarget() == null) {
                VirtualBoxManager manager = VirtualBoxManager.getInstance();
                Element rem = (Element) c.getValue();
                if(rem != null)
                if (rem.isCreated()) {
                    manager.removeVM(rem.getName());
                }

            }

            Manager.getInstance().removeElement(c.getId());
        }
    }

    private void cellsConnectedAction(mxEventObject evt) {
    }
}
